[Day22] 靈魂之王布魯克為您表演~45度角!
學寫程式也有一陣子了,但直到最近才發現很多時候自己都只是知其然而不知其所以然,而沒有完全了解自己在寫的到底是什麼。
所以這篇就要來提一些很常被用到,但還不是非常清楚的東西:
getter
?顧名思義,就是「取得(某個東西)」的方法,在 Ruby 裡,我們會把取出實體變數這件事稱為 getter
,指的就是取出實體變數的方法。
class Cat
def initialize(name)
@name = name
end
end
miru = Cat.new('miru')
miru.name
=> NoMethodError (undefined method `name' for #<Cat:0x00007ff82783a578 @name="miru">)
在類別裡,沒有 getter
就無法取出實體變數的值。所以 miru
這個實體拿不到類別裡的實體變數 @name
,如果要拿到 @name
的話,就必須給它一個 getter
。
class Cat
def initialize(name)
@name = name
end
def name #getter method
@name
end
end
miru = Cat.new('miru')
miru.name
=> "miru"
然而,如果每次要取實體變數的值都要重寫一次 getter
,嗯...用想的都覺得麻煩啊!因此超好用的 attr三兄弟
就誕生了!(登愣!)
指令 | 說明 |
---|---|
attr_reader | 用來取出實體變數。 |
attr_writer | 用來指派實體變數。 |
attr_accessor | 結合以上兩者,可取出也可指派實體變數。 |
讚嘆工程師們懶惰的美德!
attr_reader
attr_reader
可以幫助我們取出實體變數。
class Cat
attr_reader :name
def initialize(name)
@name = name
end
end
miru = Cat.new('miru')
miru.name
=> "miru"
跟剛剛完全一樣!改成用 attr_reader :name
,所以不用再寫:
def name
@name
end
一行抵三行,超級划算!
setter
?setter
也很好理解,就是「指派」的意思,在 Ruby 裡,我們會定義一個 setter
方法,透過呼叫這個方法,就可以重新指派實體變數。
attr_writer
我們延續剛剛的例子,如果今天有一隻叫做 miru
的貓
class Cat
attr_reader :name
def initialize(name)
@name = name
end
end
miru = Cat.new('miru')
miru.name
=> "miru"
而我想替祂換個更響亮的名字,結果不管怎麼寫通通都失敗了!
miru.name"neko"
=> ArgumentError (wrong number of arguments (given 1, expected 0))
miru.name."neko"
=> SyntaxError ((irb):14: syntax error, unexpected tSTRING_BEG)
miru.name = "neko"
=> NoMethodError (undefined method `name=' for #<Cat:0x00007fada005f780 @name="miru">
這是因為,在這個類別裡並沒有 setter
,因此產出的實體變數無法重新指派一個新的值。
那我們試試看加上 setter
:
class Cat
attr_reader :name
def initialize(name)
@name = name
end
def name=(name)
@name = name
end
end
miru = Cat.new('miru')
miru.name
=> "miru"
這時候就可以幫 miru
換個更好聽的名字了!
miru.name=("neko")
=> "neko"
miru.name
=> "neko"
而由於 Ruby 可以省略小括號的特性,以下這兩種 setter
的寫法可能更常見:
def name= name
@name = name
end
def name = name
@name = name
end
在使用上也可以:
miru.name = "puma"
=> "puma"
也因為這樣,才會説實體變數也是實體物件的屬性(attribute),這其中大部分的原因就是 setter
造成的!
當然,更懶惰的寫法就是用 attr_writer
啦!
class Cat
attr_reader :name
attr_writer :name
def initialize(name)
@name = name
end
end
miru = Cat.new('miru')
miru.name
=> "miru"
同樣也是一行抵三行啦!
attr_accessor
然而,沒有最懶,只有更懶。
attr_accessor
就是整合了前面兩者效果的神奇好夥伴,用了 attr_accessor
以後程式碼都變得超乾淨!等於一次擁有 attr_reader
和 attr_writer
:
class Cat
attr_accessor :name
def initialize(name)
@name = name
end
end
miru = Cat.new('miru')
miru.name
=> "miru"
miru.name = "wolf"
miru.name
=> "wolf"
是不是很心動!趕快打開 irb
玩玩看吧!
關於 attr_accessor
,大家可以拜讀龍哥這篇 Ruby 語法放大鏡之「attr_accessor 是幹嘛的?」,裡面有更多更專業的說明!
今天就介紹到這邊啦!大家明天見!